#include "oled_display.h"
#include "bsp_adc.h"
#include "chart.h"
#include "string.h"
#include "oled.h"
#include "miniscope.h"
#include <rtthread.h>
#include <stdio.h>
#include <rthw.h>
#include <math.h>
#include "stm32_dsp.h"
#include "table_fft.h"

#define accur 0.03544 

extern uint16_t ConvData;

extern uint16_t ADC_ConvertedValue[ADC_BUFF_LEN][2];


rt_thread_t adc_thread = RT_NULL;

extern void rt_hw_us_delay(rt_uint32_t us);

static struct rt_thread dis_thread;
static rt_uint8_t dis_thread_stack[DIS_THREAD_STACK_SIZE];
struct rt_timer refresh_timer;

rt_uint16_t ref_vol;

extern rt_uint8_t switch_count;
extern rt_uint8_t frequency_flag;

uint32_t adc_buf[NPT]={0};


/** 
 * @brief  字符串翻转 
 * @author wenzi
 * @date   2020/7/15
*/
static void reverse(char *str,rt_uint16_t len)
{
    uint16_t i = 0, j = len - 1,temp;
    while (i < j)
    {
        temp = str[i]; 
        str[i] = str[j];
        str[j] = temp;
        i ++;
        j --;
    }
}

/** 
 * @brief  将一个整型的数转换至字符串
 *          rt_uint16_t x:      要进行转转的整数
 *          char str[]   :      转换得到的字符串
 *          rt_uint16_t digits: 转换的位数
 * @author wenzi
 * @date   2020/7/15
*/
int int2str(rt_uint16_t x,char str[],rt_uint16_t digits)
{
    uint16_t i = 0;
    
    while (x)
    {
        str[i++] = (x % 10) + '0'; /* 将整数的每一位放进数组中 */
        x = x / 10;
    }

    while (i < digits)
    {
        str[i++] = '0';           /* 如果所要求的精度高于其要转换的整数的位数，那么就在字符前面加 0 */
    }

    reverse(str,i);               
    str[i] = '\0';

    return i;
}

/** 
 * @brief  将一个浮点型转换为字符串
 *          float n      :      要进行转转的浮点数
 *          char *res    :      转换得到的结果
 *          rt_uint16_t afterpointer: 保留的小数点位数
 * @author wenzi
 * @date   2020/7/15
*/
void flo2str(float n,char *res,rt_uint16_t afterpoint)
{
    int ipart = (int)n;                /* 提取整数部分 */
    float fpart = n - (float)ipart;    /* 提取小数部分 */

    int i = int2str(ipart,res,0);      /* 将整数转换为字符串 */

    if (afterpoint != 0)
    {
        res[i] = '.';                  /* 加入小数点 */
    }

    fpart = fpart * pow(10,afterpoint);

    int2str((int)fpart,res + i + 1,afterpoint);
}

const double eps = 1e-5;

void float_to_str(char *str,double num)
{
	int high;//float_整数部分  
    double low;//float_小数部分 
    char *start=str;
    int n=0;
    char ch[20];
    int i;
    high=(int)num;
    low=num-high;
     
	if (high == 0)
	{
		ch[0] = '0';
		n++;
	}
    while(high>0)
	{
    	ch[n++]='0'+high%10;
        high=high/10;
	}
     
    for(i=n-1;i>=0;i--)
	{
        *str++=ch[i];
    }
     
    num -= (int)num;
    double tp = 0.1;
    *str++='.';
     
    while(num > eps)
	{//精度限制 
        num -= tp * (int)(low * 10);
        tp /= 10;
        *str++='0'+(int)(low*10);
        low=low*10.0-(int)(low*10);
    }
    *str='\0';
    str=start;
 }


/* 将采样值的映射到屏幕的显示范围，并反转
   Remap sampling data to display range and inverse */
rt_uint16_t remap(rt_int16_t val, rt_int16_t rangeMax, rt_int16_t rangeMin, rt_uint16_t rangeMaxNew, rt_uint16_t rangeMinNew)
{
    if (val > rangeMax)
        val = rangeMax;
    else if (val < rangeMin)
        val = rangeMin;

    val = rangeMinNew + (rt_uint32_t)(rangeMax - val) * (rangeMaxNew - rangeMinNew) / (rangeMax - rangeMin);
    return val;
}

/* 屏幕刷新定时器 */
static void refresh_timeout(void *parameter)
{
    OLED_Display();
}

/** 
 * @brief  adc_sample_entry 数据采集线程
 * @author wenzi
 * @date   2020/8/7
*/
rt_uint8_t *convertVol(rt_int16_t v)
{
    static rt_uint8_t s[6];
	if (v > 0)
	{
		if (v < 10000)
		{
			s[0] = v / 1000 + '0';
			s[1] = '.';
			s[2] = v / 100 % 10 + '0';
			s[3] = v / 10 % 10 + '0';
			s[4] = '\0';
		}
		else
		{
			s[0] = v / 10000 + '0';
			s[1] = v / 1000 % 10 + '0';
			s[2] = '.';
			s[3] = v / 100 % 10 + '0';
			s[4] = '\0';
		}
	}
	else
	{
		if (v < -10000)
		{
			s[0] = '-';
			s[1] = v / 10000 + '0';
			s[2] = v / 1000 % 10 + '0';
			s[3] = '.';
			s[4] = v / 100 % 10 + '0';
			s[5] = '\0';			
		}
		else
		{
			s[0] = '-';
		    s[1] = v / 1000 + '0';
			s[2] = '.';
			s[3] = v / 100 % 10 + '0';
			s[4] = v / 10 % 10 + '0';
			s[5] = '\0';
		}
	}
    return s;
}

/** 
 * @brief  PowerMag 求模值
 * @author wenzi
 * @date   2020/8/13
*/
static void PowerMag(uint16_t _usFFTPoints)
{
	rt_int16_t lX,lY;
	rt_uint16_t i;
	float mag;
	
	for (i = 0; i < _usFFTPoints; i++)
	{
		lX = (miniscope.freqency.lBufOutArray[i]<<16)>>16;   /* 实部 */
		lY = (miniscope.freqency.lBufOutArray[i]>>16);       /* 虚部 */
		mag = sqrt(lX*lX + lY*lY);      /* 求模 */
		miniscope.freqency.lBufMagArray[i] = mag * 2;
	}
	miniscope.freqency.lBufMagArray[0] = miniscope.freqency.lBufMagArray[0]>>1;
}


/** 
 * @brief  PowerMag 求模值
 * @author wenzi
 * @date   2020/8/13
*/
void GetPowerMag(void)
{
    signed short lX,lY;
    float X,Y,Mag;
    unsigned short i;
    for(i=0; i<NPT/2; i++)
    {
        lX  = (miniscope.freqency.lBufOutArray[i] << 16) >> 16;
        lY  = (miniscope.freqency.lBufOutArray[i] >> 16);
			
				//除以32768再乘65536是为了符合浮点数计算规律
//        X = NPT * ((float)lX) / 32768;
//        Y = NPT * ((float)lY) / 32768;
		X = NPT * ((float)lX);
        Y = NPT * ((float)lY);
        Mag = sqrt(X * X + Y * Y)*1.0/ NPT;
//        if(i == 0)	
//            miniscope.freqency.lBufMagArray[i] = (unsigned long)(Mag * 32768);
//        else
//            miniscope.freqency.lBufMagArray[i] = (unsigned long)(Mag * 65536);
		if(i == 0)	
            miniscope.freqency.lBufMagArray[i] = (unsigned long)(Mag);
        else
            miniscope.freqency.lBufMagArray[i] = (unsigned long)(Mag * 2);
    }
}

/** 
 * @brief  adc_sample_entry 数据采集线程
 * @author wenzi
 * @date   2020/8/7
*/
void adc_sample_entry(void *paramter)
{
	rt_uint32_t v = 0;
	rt_uint16_t out_temp;
	rt_int16_t result_temp;
	char buffer[5];
	rt_uint16_t adc_temp;
	float sample_frequency;
	
	int i,t;

	while(1)
	{
		t = miniscope.menu[MENU_TYPE_TIME_SCALE].value[miniscope.menu[MENU_TYPE_TIME_SCALE].index];
		miniscope.adc.interval_us = SCALE_TO_INTERVAL(t);
		if (frequency_flag % 2 == 0)
		{
			rt_sem_take(miniscope.adc.adc_complete_sem,RT_WAITING_FOREVER);
			for (i = 0; i < ADC_SAMPLE_NUM; i++)
			{
				miniscope.adc.buff[i] = ADC_ConvertedValue[i][1] - ADC_ConvertedValue[i][0];
				miniscope.adc.Vout = ADC_ConvertedValue[i][1] * 3.3 / 4096;
				miniscope.adc.B_Value = miniscope.adc.Vout / (12.2 * 51 * 4); 
			}
			
			for (i = 0; i < ADC_BUFF_LEN;i++)
			{
				miniscope.freqency.lBufInArray[i] = ADC_ConvertedValue[i][1] << 16;
			}
			cr4_fft_256_stm32(miniscope.freqency.lBufOutArray,miniscope.freqency.lBufInArray, NPT);
			GetPowerMag();

			miniscope.freqency.frequency_max = 0;
			miniscope.freqency.frequency_min = 0;

			for (i = 1; i < ADC_BUFF_LEN / 2; i++)
			{
				if (miniscope.freqency.lBufMagArray[i] > miniscope.freqency.frequency_max)
				{
					miniscope.freqency.frequency_max = miniscope.freqency.lBufMagArray[i];
					miniscope.freqency.frequency_max_position = i;
				}
				else if (miniscope.freqency.lBufMagArray[i] < miniscope.freqency.frequency_min)
				{
					miniscope.freqency.frequency_min = miniscope.freqency.lBufMagArray[i];
				}
			}
			sample_frequency = 72000000.0 / (float)((miniscope.freqency.sample_arr + 1) * (miniscope.freqency.sample_psc + 1));
			miniscope.wave.wave_frequency = miniscope.freqency.frequency_max_position * sample_frequency / NPT;
			
			rt_mb_send_wait(miniscope.adc.mb,(rt_uint32_t)&miniscope.adc.buff[0],RT_WAITING_FOREVER);
		}
		else
		{
			rt_sem_take(miniscope.adc.adc_complete_sem,RT_WAITING_FOREVER);
			for (i = 0; i < ADC_BUFF_LEN;i++)
			{
				miniscope.freqency.lBufInArray[i] = ADC_ConvertedValue[i][1] << 16;
			}
			cr4_fft_256_stm32(miniscope.freqency.lBufOutArray,miniscope.freqency.lBufInArray, NPT);
			GetPowerMag();

			miniscope.freqency.frequency_max = 0;
			miniscope.freqency.frequency_min = 0;

			for (i = 1; i < ADC_BUFF_LEN / 2; i++)
			{
				if (miniscope.freqency.lBufMagArray[i] > miniscope.freqency.frequency_max)
				{
					miniscope.freqency.frequency_max = miniscope.freqency.lBufMagArray[i];
					miniscope.freqency.frequency_max_position = i;
				}
				else if (miniscope.freqency.lBufMagArray[i] < miniscope.freqency.frequency_min)
				{
					miniscope.freqency.frequency_min = miniscope.freqency.lBufMagArray[i];
				}
			}
			sample_frequency = 72000000.0 / (float)((miniscope.freqency.sample_arr + 1) * (miniscope.freqency.sample_psc + 1));
			miniscope.wave.wave_frequency = miniscope.freqency.frequency_max_position * sample_frequency / NPT;
			rt_mb_send_wait(miniscope.freqency.mb, (rt_uint32_t)&miniscope.freqency.lBufMagArray[0], RT_WAITING_FOREVER);
		}
	}
}

void data_parse_entry(void *parameter)
{
    rt_int16_t *adc_buff = RT_NULL;
    rt_int16_t tmp = 0;
    rt_int16_t dacMax = 0, dacMin = 4095, dacMid = 0;
    rt_int16_t plotADCMax = 0, plotADCMin = 0;
	int i, option_index;
	
    while (1)
	{
		if (rt_mb_recv(miniscope.adc.mb, (rt_uint32_t *)&adc_buff, RT_WAITING_FOREVER) == RT_EOK)
		{
			for (i = 0; i < ADC_SAMPLE_NUM; i++)
            {
                tmp = adc_buff[i];
                if (tmp > dacMax)
                    dacMax = tmp;
                else if (tmp < dacMin)
                    dacMin = tmp;
            }

            //将采样点的最大最小ADC值转换成电压值mV
            miniscope.wave.vMax = (rt_int32_t)dacMax * 3300 / 4096;
            miniscope.wave.vMin = (rt_int32_t)dacMin * 3300 / 4096;
			
            //用垂直标尺mV范围反求出ADC值的范围作为图表的显示上下限
            plotADCMax = (rt_int32_t)miniscope.wave.rulerVMax * 4096 / 3300;
            plotADCMin = (rt_int32_t)miniscope.wave.rulerVMin * 4096 / 3300;

            //查询触发位置
            dacMid = (dacMax + dacMin) >> 1;
            miniscope.tri_pos = ADC_SAMPLE_NUM / 2;

            for (i = 50; i <= ADC_SAMPLE_NUM-50; i++)
            {
                if (miniscope.menu[MENU_TYPE_TRI_DIR].index == TRIG_DIRE_RISING) //上升触发
                {
                    if (adc_buff[i] <= dacMid && adc_buff[i+1] >= dacMid)
                    {
                        miniscope.tri_pos = i;
                        break;
                    }
                }
                else //下降触发
                {
                    if (adc_buff[i] >= dacMid && adc_buff[i+1] <= dacMid)
                    {
                        miniscope.tri_pos = i;
                        break;
                    }
                }
            }

            //重新映射采样点ADC值至图表的垂直范围
            for (i = 0; i < ADC_SAMPLE_NUM; i++)
            {
                miniscope.wave.data[i] = remap(adc_buff[i], plotADCMax, plotADCMin, 52, 1);
            }
            rt_mb_send_wait(miniscope.wave.mb, (rt_uint32_t)&miniscope.wave.data[0], RT_WAITING_FOREVER);
		}
	}
}

/** 
 * @brief  AnalyseData 数据函数
 * @author wenzi
 * @date   2020/7/27
*/
void PlotChart(void)
{
    rt_uint8_t i;
    rt_uint8_t *s;
	char buffer[5];
    
	OLED_Clear();

	//绘制图表实线边框
	OLED_DrawHLine(26, 0, 4); //方框内纵向留52格,1~52
	OLED_DrawHLine(26, 53, 4);
	
	OLED_DrawHLine(123, 0, 4);
	OLED_DrawHLine(123, 53, 4);
	OLED_DrawVLine(25, 0, 54); //方框内横向留101格,26~126
	OLED_DrawVLine(127, 0, 54);

	//绘制图表虚线网格
	for (i = 0; i < 17; i++)
	{
		OLED_DrawHLine(28 + 6 * i, 26, 2);
	}
	for (i = 0; i < 9; i++)
	{
		OLED_DrawVLine(26 + 25, 2 + i * 6, 2);
		OLED_DrawVLine(26 + 50, 2 + i * 6, 2);
		OLED_DrawVLine(26 + 75, 2 + i * 6, 2);
	}

	//绘制触发方式标志
	if(miniscope.option_index == MENU_TYPE_TRI_DIR)
	{
		OLED_Reverse(1);
	}

	if (miniscope.menu[MENU_TYPE_TRI_DIR].index == TRIG_DIRE_RISING)
	{
		OLED_DrawChar(18, 56, 123); //123上箭头，上升沿触发
	}
	else
	{
		OLED_DrawChar(18, 56, 124); //124下箭头，下降沿触发
	}
	OLED_Reverse(0);
	
	//绘制波形电压范围
	OLED_Set_Pos(26, 56);
	
	if(miniscope.menu[MENU_TYPE_VOLT_SCALE].index == VOLT_SCALE_Auto)
	{
		OLED_Set_Pos(8, 56);
		OLED_DrawString("A");
	}

	if(miniscope.option_index == MENU_TYPE_TIME_SCALE)
	{
		OLED_Reverse(1);
	}
	OLED_Set_Pos(90, 56);
	float_to_str(buffer,miniscope.wave.wave_frequency);
	OLED_DrawString(buffer);
	OLED_Reverse(0);
		
	if(miniscope.option_index == MENU_TYPE_VOLT_SCALE)
	{
		OLED_Reverse(1);
	}
	s = convertVol(miniscope.wave.rulerVMax);
	OLED_Set_Pos(0, 0);
	OLED_DrawString(s);
	OLED_Reverse(0);
	
	OLED_Set_Pos(10, 26);
	OLED_DrawString("0");
	
	if (switch_count % 2 == 0)
	{
		OLED_Set_Pos(27, 56);
		float_to_str(buffer,miniscope.adc.B_Value);
		OLED_DrawString(buffer);
		OLED_Set_Pos(69, 56);
		OLED_DrawString("mT");
	}
	else
	{
		OLED_Set_Pos(27, 56);
		float_to_str(buffer,miniscope.adc.B_Value * 10);
		OLED_DrawString(buffer);
		OLED_Set_Pos(69, 56);
		OLED_DrawString("Gs");	
	}
	
	if (switch_count == 255)
	{
		OLED_Set_Pos(27, 56);
		float_to_str(buffer,miniscope.adc.Vout);
		OLED_DrawString(buffer);
		OLED_Set_Pos(69, 56);
		OLED_DrawString("V ");
	}
}

/** 
 * @brief  波形数据初始化函数
 * @author wenzi
 * @date   2020/8/13
*/
void Plot_Frequency_Chart(void)
{
	rt_uint8_t i;
	OLED_Clear();

	//绘制图表实线边框
	OLED_DrawHLine(26, 0, 4); //方框内纵向留52格,1~52
	//OLED_DrawHLine(23, 26, 3);
	OLED_DrawHLine(26, 53, 4);
	
	OLED_DrawHLine(123, 0, 4);
	OLED_DrawHLine(123, 53, 4);
	OLED_DrawVLine(25, 0, 54); //方框内横向留101格,26~126
	OLED_DrawVLine(127, 0, 54);

	//绘制图表虚线网格
	for (i = 0; i < 9; i++)
	{
		OLED_DrawVLine(26 + 25, 2 + i * 6, 2);
		OLED_DrawVLine(26 + 50, 2 + i * 6, 2);
		OLED_DrawVLine(26 + 75, 2 + i * 6, 2);
	}
}


/** 
 * @brief  波形数据初始化函数
 * @author wenzi
 * @date   2020/8/7
*/
int wavedata_init(void)
{
	rt_thread_t parse_thread = RT_NULL;

	adc_thread = rt_thread_create("adc_thread",
								adc_sample_entry,
								RT_NULL,
								ADC_THREAD_STACK_SIZE,
								ADC_THREAD_PRIO,
								30);

	if (adc_thread != RT_NULL)
	{
		rt_thread_startup(adc_thread);
	}

	parse_thread = rt_thread_create("parse_thread",
									data_parse_entry,
	                                RT_NULL,
									PARSE_THREAD_STACK_SIZE,
									PARSE_THREAD_PRIO,
									30);
	if (parse_thread != RT_NULL)
	{
		rt_thread_startup(parse_thread);
	}
}

/* 显存更新线程入口 */
void dis_thread_entry(void *parameter)
{
	rt_uint16_t tempVal = 0;
	rt_uint16_t *dis_buff = RT_NULL;
	rt_uint32_t *frequ_buff = RT_NULL;
	rt_uint16_t freq_max = 0;
	rt_uint16_t freq_min = 0;
	rt_uint16_t tmp;
	float frequency_L;
	float frequency_M;
	char buffer[5];
	float max_vol;
	
	int i;

	while (1)
	{
		if (frequency_flag % 2 == 0)
		{
			if (rt_mb_recv(miniscope.wave.mb, (rt_uint32_t *)&dis_buff, RT_WAITING_FOREVER) == RT_EOK)
			{
				PlotChart();
				for (i = 0; i < 100; i++)
				{
					OLED_DrawLine(i+26, dis_buff[i+(miniscope.tri_pos-50)], i+26+1, dis_buff[i+1+(miniscope.tri_pos-50)]);
				}
				rt_timer_start(&refresh_timer);
			}
		}
		else
		{
			if (rt_mb_recv(miniscope.freqency.mb,(rt_uint32_t*)&frequ_buff,RT_WAITING_FOREVER) == RT_EOK)
			{
				OLED_Clear();
				OLED_Set_Pos(0, 56);
				OLED_DrawString("Max vol:");
				
				max_vol = miniscope.freqency.frequency_max * 3300 / 4096;
				float_to_str(buffer,max_vol);
				OLED_Set_Pos(48, 56);
				OLED_DrawString(buffer);
				
				OLED_Set_Pos(80, 56);
				flo2str(miniscope.wave.wave_frequency,buffer,2);
				OLED_DrawString(buffer);
				OLED_Set_Pos(115, 56);
				OLED_DrawString("hz");
				
				
				if (miniscope.freqency.frequency_max == 0) /* 防止当最大值为 0 时谱线占满整个屏幕 */
				{
					miniscope.freqency.frequency_max = 10;
				}
				
				for (i = 1; i < 128; i++)
				{
					miniscope.freqency.fre_wave[i] = remap(frequ_buff[i],miniscope.freqency.frequency_max,miniscope.freqency.frequency_min,52,1); 
					OLED_DrawVerLine(i,miniscope.freqency.fre_wave[i],53);
//					OLED_DrawVerLine(i,frequ_buff[i],53);
				}
				rt_timer_start(&refresh_timer);
			}
		}
	}
}


int display_init(void)
{
	rt_timer_init(&refresh_timer, "timer1", refresh_timeout, RT_NULL, 1, RT_TIMER_FLAG_ONE_SHOT);
	rt_thread_init(&dis_thread, "dis_thread", dis_thread_entry, RT_NULL, dis_thread_stack, DIS_THREAD_STACK_SIZE, DIS_THREAD_PRIO, 10);

    rt_timer_start(&refresh_timer);
    rt_thread_startup(&dis_thread);
}

